package iohelper

import (
	"fmt"
	"io"
)

// 读取动态长度
func ReadDynLen(r io.Reader) (ret uint64, err error) {
	b := []byte{0}
	for i := 0; i < 10; i++ {
		if _, err = r.Read(b); err != nil {
			return
		}
		ret = ret | uint64(b[0]&0b1111111)<<(i*7)
		if b[0]&0b10000000 == 0 { // 高位有1，说明后面还有数字
			break
		}
	}
	return
}

// 读取动态长度
func WriteDynLen(w io.Writer, nlen uint64) (n int, err error) {
	b := []byte{0}
	for {
		b[0] = byte(nlen & 0b1111111)
		nlen = nlen >> 7
		if nlen != 0 {
			b[0] |= 0b10000000
		}
		if _, err = w.Write(b); err != nil {
			return
		} else {
			n++
			if nlen == 0 { // 没有剩余长度了
				break
			}
		}
	}
	return
}

func GetLengthDataLen(l int) int {
	n := 1
	for {
		l >>= 7
		if l > 0 {
			n++
		} else {
			break
		}
	}
	return n
}

func AddLengthDataLen(l int) int {
	return GetLengthDataLen(l) + l
}

// 根据 ss 的长度读取数据
func ReadSlice(r *ReadHelper, ss any) (n int, err error) {
	switch v := ss.(type) {
	case []byte:
		n, err = r.Read(v)
	case []uint16:
		for i := range v {
			v[i], err = r.ReadUint16()
			if err != nil {
				return
			}
			n += 2
		}
	case []uint32:
		for i := range v {
			v[i], err = r.ReadUint32()
			if err != nil {
				return
			}
			n += 4
		}
	case []uint64:
		for i := range v {
			v[i], err = r.ReadUint64()
			if err != nil {
				return
			}
			n += 8
		}
	case []string:
		for i := range v {
			v[i], err = r.ReadString()
			if err != nil {
				return
			}
			l := len(v[i])
			n += l + GetLengthDataLen(l)
		}
	default:
		err = fmt.Errorf("未处理的类型 %v", v)
	}
	return
}

// 不用写入头部的长度，只写纯数据
func WriteSlice(w *WriteHelper, ss any) (n int, err error) {
	var l int
	switch v := ss.(type) {
	case []byte:
		n, err = w.Write(v)
	case []uint16:
		for _, i := range v {
			l, err = w.WriteUint16(i)
			if err != nil {
				return
			}
			n += l
		}
	case []uint32:
		for _, i := range v {
			l, err = w.WriteUint32(i)
			if err != nil {
				return
			}
			n += l
		}
	case []uint64:
		for _, i := range v {
			l, err = w.WriteUint64(i)
			if err != nil {
				return
			}
			n += l
		}
	case []string:
		for _, s := range v {
			l, err = w.WriteString(s)
			if err != nil {
				return
			}
			n += l
		}
	default:
		err = fmt.Errorf("未处理的类型 %v", v)
	}
	return
}
